﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading.Tasks;
using System.Threading;
using ZCrawler;
using NCrawler.Extensions;
using DevExpress.XtraEditors;
using DevExpress.XtraBars;

namespace ZCrawlerManager
{
    public partial class Form1 : DevExpress.XtraEditors.XtraForm
    {
        public Form1()
        {
            InitializeComponent();
            TaskPool.Init();
            TaskPool.procedures.ForEach(p =>
                {
                    p.task.onStepDataOut = new Action<ZTask, ZResult>((t, a_r) =>
                    {
                        MasterToDetail(t);
                    });
                    p.task.willStartTask = new Action<ZTask>((t) =>
                    {
                        BindWithoutSave(t);
                    });
                    p.task.didTaskCompleted = new Action<ZTask>((t) =>
                    {
                        BindWithoutSave(t);
                    });
                    p.task.onStatusChanged = new Action<ZTask>((t) =>
                    {
                        BindWithoutSave(t);
                    });
                });
            Templates.Init();
            LoadTemplates();
            Bind();
        }
        private void LoadTemplates()
        {
            btnFromTemplate.ClearLinks();
            btnDeleteTemplate.ClearLinks();
            Templates.templates.ForEach(t =>
            {
                BarItem item = new BarButtonItem(null, t.title);
                item.ItemClick += item_ItemClick;
                btnFromTemplate.AddItem(item);
            });
            Templates.templates.ForEach(t =>
            {
                BarItem item = new BarButtonItem(null, t.title);
                item.ItemClick += delete_item_ItemClick;
                btnDeleteTemplate.AddItem(item);
            });
        }
        void delete_item_ItemClick(object sender, ItemClickEventArgs e)
        {
            Templates.templates.RemoveAt(
                        Templates.templates.FindIndex(t=>
                        {
                            return t.title.Equals(e.Item.Caption);
                        })
                    );
                Templates.Update();
                LoadTemplates();
        }

        void item_ItemClick(object sender, ItemClickEventArgs e)
        {
            ZTemplate template = Templates.templates.Find(t => t.title.Equals(e.Item.Caption));
            List<ZBasicRule> rules = new List<ZBasicRule>();
            template.fields.ForEach(f =>
            {
                ZBasicRule rule = new ZBasicRule()
                {
                    FieldName = f
                };
                rules.Add(rule);
            });
            ZAnalysis tmpAnalysis = new ZAnalysis(rules);
            ZTask tsk = new ZTask()
            {
                analysis = tmpAnalysis
            };
            using (FrmTask frm = new FrmTask(tsk))
            {
                frm.ShowDialog();
                if (frm.result == System.Windows.Forms.DialogResult.OK)
                {
                    ZTask task = frm.task;
                    task.onStepDataOut = new Action<ZTask, ZResult>((t, a_r) =>
                    {
                        MasterToDetail(t);
                    });
                    task.willStartTask = new Action<ZTask>((t) =>
                    {
                        BindWithoutSave(t);
                    });
                    task.didTaskCompleted = new Action<ZTask>((t) =>
                    {
                        BindWithoutSave(t);
                    });
                    Procedure p = new Procedure();
                    p.task = task;
                    p.TaskID = task.TaskID;
                    TaskPool.procedures.Add(p);
                    Bind();
                }
            }
        }

        private void btnAdd_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            using(FrmTask frm = new FrmTask())
            {
                frm.ShowDialog();
                if(frm.result == System.Windows.Forms.DialogResult.OK)
                {
                    ZTask task = frm.task;
                    task.onStepDataOut = new Action<ZTask, ZResult>((t, a_r) =>
                    {
                        MasterToDetail(t);
                    });
                    task.willStartTask = new Action<ZTask>((t) =>
                    {
                        BindWithoutSave(t);
                    });
                    task.didTaskCompleted = new Action<ZTask>((t) =>
                    {
                        BindWithoutSave(t);
                    });
                    Procedure p = new Procedure();
                    p.task = task;
                    p.TaskID = task.TaskID;
                    TaskPool.procedures.Add(p);
                    Bind();
                }
            }
        }

        private void Bind()
        {
            gcTask.DataSource = TaskPool.procedures;
            gvTask.RefreshData();
        }

        private void BindWithoutSave(ZTask t)
        {
            int index = TaskPool.procedures.FindIndex(proc => { return proc.TaskID.Equals(t.TaskID); });
            int handle = gvTask.GetRowHandle(index);
            gvTask.RefreshRow(handle);
        }

        private void MasterToDetail(object datasource)
        {
            try
            {
                ZTask t = datasource as ZTask;
                int handle = gvTask.FocusedRowHandle;
                int index = gvTask.GetDataSourceRowIndex(handle);
                if (TaskPool.procedures[index].task.status != ZTaskStatus.Idle || TaskPool.procedures[index].task.resultSet.Count != 0)
                {
                    if (t.TaskID == TaskPool.procedures[index].TaskID)
                    {
                        if (this.InvokeRequired)
                        {
                            this.Invoke(new Action(() =>
                            {
                                gcDetail.DataSource = t.resultSet.results();
                                gvDetail.PopulateColumns();
                                gvDetail.RefreshData();
                                gvDetail.MoveLast();
                            }));
                        }
                        else
                        {
                            gcDetail.DataSource = t.resultSet.results();
                            gvDetail.PopulateColumns();
                            gvDetail.RefreshData();
                            gvDetail.MoveLast();
                        }
                    }
                }
            }
            catch (Exception)
            { }
        }

        private void btnDelete_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            int handle = gvTask.FocusedRowHandle;
            int dataSourceIndex = gvTask.GetDataSourceRowIndex(handle);
            TaskPool.procedures.RemoveAt(dataSourceIndex);
            Bind();
        }

        private void btnRun_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            int handle = gvTask.FocusedRowHandle;
            int dataSourceIndex = gvTask.GetDataSourceRowIndex(handle);
            Procedure t = TaskPool.procedures[dataSourceIndex];
            t.onCompletionHandler = new Action<ZTask>((zt) =>
            {
                BindWithoutSave(zt);
            });
            t.Start();
        }

        private void btnStop_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            try
            {
                int handle = gvTask.FocusedRowHandle;
                int dataSourceIndex = gvTask.GetDataSourceRowIndex(handle);
                TaskPool.procedures[dataSourceIndex].Stop();
                gvTask.RefreshRow(handle);
            }
            catch (Exception) { }
        }

        private void gvTask_FocusedRowChanged(object sender, DevExpress.XtraGrid.Views.Base.FocusedRowChangedEventArgs e)
        {
            
        }

        private void gvTask_RowClick(object sender, DevExpress.XtraGrid.Views.Grid.RowClickEventArgs e)
        {
            if(e.Clicks == 1)
            {
                int dataSourceIndex = gvTask.GetDataSourceRowIndex(e.RowHandle);
                ZTask task = TaskPool.procedures[dataSourceIndex].task;
                btnRun.Enabled = task.status == ZTaskStatus.Idle;
                MasterToDetail(task);
            }
            if(e.Clicks == 2)
            {
                int handle = e.RowHandle;
                int index = gvTask.GetDataSourceRowIndex(handle);
                if (TaskPool.procedures[index] == null) return;
                if(TaskPool.procedures[index].task.status != ZTaskStatus.Idle)
                {
                    DevExpress.XtraEditors.XtraMessageBox.Show("{0} is a running task, could not edit.".FormatWith(TaskPool.procedures[index].TaskID));
                    return;
                }
                using(FrmTask frm = new FrmTask(TaskPool.procedures[index].task))
                {
                    frm.ShowDialog();
                    if(frm.result == System.Windows.Forms.DialogResult.OK)
                    {
                        TaskPool.procedures[index].task = frm.task;
                        TaskPool.procedures[index].TaskID = frm.task.TaskID;
                        Bind();
                    }
                }
            }
        }

        private void barButtonItem1_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            using(FrmTemplate frm = new FrmTemplate())
            {
                frm.ShowDialog();
                if(frm.result == System.Windows.Forms.DialogResult.OK)
                {
                    Templates.templates.Add(frm.template);
                    Templates.Update();
                    LoadTemplates();
                }
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            TaskPool.procedures.ForEach(p =>
                {
                    p.Stop();
                    p.task.Clean();
                });
            TaskPool.Commit();
        }

        private void btnExport_ItemClick(object sender, ItemClickEventArgs e)
        {
            using(SaveFileDialog dialog = new SaveFileDialog())
            {
                if(dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    string fileToSave = dialog.FileName;
                    gvDetail.ExportToXls(fileToSave);
                }
            }
        }

        private void barButtonItem2_ItemClick(object sender, ItemClickEventArgs e)
        {
            TaskPool.Commit();
        }
    }
}
